/***************************************************************************//**
 * @file camera_array_settings.cpp
 * @brief Allows settings to be changed for UVC compliant webcams
 *
 * @page "Camera Settings" Camera Settings
 *
 * @authors Brian Fehrman
 * 
 * @date April 17 2013
 * 
 * @section file_section File Information
 *
 * @details Implementation file for the camera_settings functions
 *       which are used to set various camera properties
 *       for UVC compliant cameras using linux system
 *       calls and uvcdynctrl. MUST HAVE uvcdynctrl
 *       INSTALLED!
 * 
 * @section settings_section Required Settings
 * 
   @verbatim
   [exposure_absolute] - absolute auto exposure value (int)
   [exposure_auto] - auto exposure mode (int)
   [exposure_auto_priority] - auto exposure priority on/off (int)
   [white_balance_temperature_auto] - auto white balance temperature on/off (int)
   [vid_list] - list of /dev/video numbers for cameras (vector<int>)
   @endverbatim
 * 
 * @section todo_bugs_modification_section Todo, Bugs, and Modifications
 *
 * @todo Add ability to set cameras individually with different settings
 ******************************************************************************/

////////// Includes ///////////
#include "camera_array_settings.h"

/***************************************************************************//**
 * @author Brian Fehrman
 *
 * @par Description:
 * Change the settings for each camera. Right now
 * it makes the settings the same for all cameras.
 * Future update could include setting each camera individually.
 *
 * @param[in] fs - FileNode pointing to the settings that are needed
 *
 * @returns 0 - everything went fine
 ******************************************************************************/
int init_cams( FileNode fs )
{
   int exp_abs;
   int exp_auto;
   int exp_auto_pri;
   int white_bal_temp_auto;
   vector< int > vid_list;
   
   fs["exposure_absolute"] >> exp_abs;
   fs["exposure_auto"] >> exp_auto;
   fs["exposure_auto_priority"] >> exp_auto_pri;
   fs["white_bal_temp_auto"] >> white_bal_temp_auto;
   fs["vid_list"] >> vid_list;
   
   //Change settings for each camera. Be careful on the order
   //in which the different auto exposure settings are called
   for( unsigned int vid = 0; vid < vid_list.size(); vid++ )
   {
      set_exposure_auto_priority( vid_list[ vid ], exp_auto_pri );
      set_exposure_auto( vid_list[ vid ], exp_auto );
      set_exposure_absolute( vid_list[ vid ], exp_abs );
      set_white_balance_temperatue_auto( vid_list[ vid ], white_bal_temp_auto );
   }
   
   return 0;
}

/***************************************************************************//**
 * @author Brian Fehrman
 *
 * @par Description:
 * Sets the absolute exposure level of the camera. Make sure that you set 
 * "Exposure, Auto" to 1 (manual mode) and "Exposure, Auto Priority" to 0
 * (auto exposure off) before calling this function.
 *
 * @param[in] vid_num - /dev/video number of camera for which to change the settings
 * @param[in] new_setting - New absolute exposure value. Input Range: [ 1, 10000 ] where less is more
 * 
 * @returns false - system call failed
 * @return true - system call success
 ******************************************************************************/
bool set_exposure_absolute( int vid_num, int new_setting )
{
   static const string EXP_ABS_CALL = " -s \"Exposure (Absolute)\" ";
   string sys_call;
   stringstream vid, set;
   
   vid << vid_num;
   set << new_setting; 
   
   sys_call = BASE_CALL + vid.str() + EXP_ABS_CALL + set.str();
   
   if ( system( sys_call.c_str( ) ) )
      return false;
   
   return true;
}

/***************************************************************************//**
 * @author Brian Fehrman
 *
 * @par Description:
 * Sets exposure mode to manual or auto. Need to call this function once and 
 * set to manual before calling set_exposure_absolute.
 *
 * @param[in] vid_num - /dev/video number of camera for which to change the settings
 * @param[in] new_setting - New auto exposure mode setting :   1 - Manual Mode, 
 *                                                             3 - Auto Exposure Mode
 * 
 * @returns false - system call failed
 * @return true - system call success
 ******************************************************************************/
bool set_exposure_auto( int vid_num, int new_setting )
{
   static const string AUTO_EXP_CALL = " -s \"Exposure, Auto\" ";
   string sys_call;
   stringstream vid, set;
   
   vid << vid_num;
   set << new_setting; 
   
   sys_call = BASE_CALL + vid.str() + AUTO_EXP_CALL + set.str();
   
   if ( system( sys_call.c_str( ) ) )
      return false;
   
   return true;
}

/***************************************************************************//**
 * @author Brian Fehrman
 *
 * @par Description:
 * Turn auto priortity exposure on or off
 *
 * @param[in] vid_num - /dev/video number of camera for which to change the settings
 * @param[in] new_setting - New auto priority exposure mode setting :   0 - Off, 
 *                                                                      1 - On
 * 
 * @returns false - system call failed
 * @return true - system call success
 ******************************************************************************/
bool set_exposure_auto_priority( int vid_num, int new_setting )
{
   static const string AUTO_EXP_CALL = " -s \"Exposure, Auto Priority\" ";
   string sys_call;
   stringstream vid, set;
   
   vid << vid_num;
   set << new_setting; 
   
   sys_call = BASE_CALL + vid.str() + AUTO_EXP_CALL + set.str();
   
   if ( system( sys_call.c_str( ) ) )
      return false;
   
   return true;
}

/***************************************************************************//**
 * @author Brian Fehrman
 *
 * @par Description:
 * Turn auto white balance on or off
 *
 * @param[in] vid_num - /dev/video number of camera for which to change the settings
 * @param[in] new_setting - New auto white balance mode setting :    0 - Off, 
 *                                                                   1 - On
 * 
 * @returns false - system call failed
 * @return true - system call success
 ******************************************************************************/
bool set_white_balance_temperatue_auto( int vid_num, int new_setting )
{
   static const string WHITE_BAL_CALL = " -s \"White Balance Temperature, Auto\" ";
   string sys_call;
   stringstream vid, set;
   
   vid << vid_num;
   set << new_setting; 
   
   sys_call = BASE_CALL + vid.str() + WHITE_BAL_CALL + set.str();
   
   if ( system( sys_call.c_str( ) ) )
      return false;
   
   return true;
}
